package com.talent.proxy.mysql.common.packets.s2c;

import java.nio.ByteBuffer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.talent.aio.common.Aio;
import com.talent.aio.common.ChannelContext;
import com.talent.proxy.mysql.common.MysqlExt;
import com.talent.proxy.mysql.common.MysqlExt.SessionStatus;
import com.talent.proxy.mysql.common.MysqlPacket;
import com.talent.proxy.mysql.common.MysqlReturn;
import com.talent.proxy.mysql.common.utils.BufferUtil;

/**
 * 
 * <pre>
 * <div class="informaltable"><table class="informaltable" border="0">
<colgroup>
<col class="type">
<col class="name">
<col class="desc">
</colgroup>
<thead><tr>
<th scope="col">Type</th>
<th scope="col">Name</th>
<th scope="col">Description</th>
</tr></thead>
<tbody>
<tr>
<td scope="row"><a class="link" href="describing-packets.html#type-1"><span class="type">int&lt;1&gt;</span></a></td>
<td><em class="structfield"><code><a name="cs-packet-err-header"></a>header</code></em></td>
<td>
<code class="literal">[ff]</code> header of the ERR packet</td>
</tr>
<tr>
<td scope="row"><a class="link" href="describing-packets.html#type-2"><span class="type">int&lt;2&gt;</span></a></td>
<td><em class="structfield"><code><a name="cs-packet-err-error-code"></a>error_code</code></em></td>
<td>error-code</td>
</tr>
<tr><td scope="row" colspan="3"><code class="code">if capabilities &amp;
                  <a class="link" href="capability-flags.html#flag-CLIENT_PROTOCOL_41">CLIENT_PROTOCOL_41</a>
                  {</code></td></tr>
<tr>
<td scope="row"><code class="code">&nbsp;&nbsp;<a class="link" href="describing-packets.html#type-string.fix_len">string[1]</a></code></td>
<td><em class="structfield"><code><a name="cs-packet-err-sqlstate-marker"></a>sql_state_marker</code></em></td>
<td>
<code class="literal">#</code> marker of the SQL State</td>
</tr>
<tr>
<td scope="row"><code class="code">&nbsp;&nbsp;<a class="link" href="describing-packets.html#type-string.fix_len">string[5]</a></code></td>
<td><em class="structfield"><code><a name="cs-packet-err-sqlstate"></a>sql_state</code></em></td>
<td>SQL State</td>
</tr>
<tr><td scope="row" colspan="3"><code class="code">}</code></td></tr>
<tr>
<td scope="row"><a class="link" href="describing-packets.html#type-string.EOF"><span class="type">string&lt;EOF&gt;</span></a></td>
<td><em class="structfield"><code><a name="cs-packet-err-message"></a>error_message</code></em></td>
<td>human readable error message</td>
</tr>
</tbody>
</table></div>
 * 
 * 
 * </pre>
 * @see http://dev.mysql.com/doc/internals/en/packet-ERR_Packet.html
 */
public class ErrorPacket extends MysqlPacket
{
	private static Logger log = LoggerFactory.getLogger(ErrorPacket.class);
	public static final byte MARK = (byte) 0xff;
	public int errno;
	public byte mark = (byte) '#';
	public byte[] sqlState = "HY000".getBytes();
	public byte[] message;
	public String messageStr;

	@Override
	public void decodeBody(ByteBuffer buffer, ChannelContext<MysqlExt, MysqlPacket, MysqlReturn> channelContext)
	{

		BufferUtil.read(buffer);
		errno = BufferUtil.readUB2(buffer);
		if (buffer.hasRemaining() && (buffer.get(buffer.position()) == (byte) '#'))
		{
			BufferUtil.read(buffer);
			sqlState = BufferUtil.readBytes(buffer, 5);
		}
		message = BufferUtil.readBytes(buffer);
		messageStr = new String(message);
	}

	@Override
	public ByteBuffer encode(ChannelContext<MysqlExt, MysqlPacket, MysqlReturn> channelContext)
	{
		int bodySize = bodySize();
		ByteBuffer buffer = ByteBuffer.allocate(HEADER_SIZE + bodySize);
		BufferUtil.writeUB3(buffer, bodySize);
		buffer.put(seqId);
		buffer.put(MARK);
		BufferUtil.writeUB2(buffer, errno);
		buffer.put(mark);
		buffer.put(sqlState);
		buffer.put(message);
		return buffer;
	}

	@Override
	public int bodySize()
	{
		int size = 9;// 1 + 2 + 1 + 5
		if (message != null)
		{
			size += message.length;
		}
		return size;
	}

	@Override
	protected String packetDesc()
	{
		return "MySQL Error Packet";
	}

	/** 
	 * @see com.talent.proxy.mysql.common.MysqlPacket#onReceived(com.talent.aio.common.ChannelContext)
	 * 
	 * @param channelContext
	 * @return
	 * @重写人: tanyaowu
	 * @重写时间: 2017年1月23日 下午4:59:48
	 * 
	 */
	@Override
	public MysqlReturn onReceived(ChannelContext<MysqlExt, MysqlPacket, MysqlReturn> channelContext)
	{

		MysqlExt mysqlExt = channelContext.getSessionContext();
		SessionStatus sessionStatus = mysqlExt.getSessionStatus();
		switch (sessionStatus)
		{
		case CLIENT_WAITING_AUTH_RESP:
		{
			String msg = "";
			if (this.message != null && this.message.length > 0)
			{
				msg = new String(message);
			}
			String remark = "认证阶段服务器返回错误包:" + msg;
			log.error(remark);
			Aio.close(channelContext, remark);
			break;
		}
		default:
			break;
		}
		return null;

	}

}
